/*write.cpp
 *This program writes specified file to specified block on created RAID.
 *Created on: 2013.12.24
 *Author: Petrunin D.S.
 */
#ifndef UTILS_H_
#define UTILS_H_

#include <iostream>
#include <stdio.h>

#ifdef WIN32
#include <Windows.h>
#else
#include <sys/types.h>
#include <sys/mman.h>
#endif

using namespace std;

bool failedDisk(int nDisks, bool rebuild) {
	char DiskNm[10];
	FILE * disk;
	for (int i = 1; i <= nDisks; i++) {
		sprintf(DiskNm, "Disk%i", i);
		disk = fopen(DiskNm,"rb+");
		if (disk == NULL) {
			if (!rebuild)
				cout << "Can't open file "<< DiskNm <<"\n";
			return true;
		}
		fclose(disk);
	}
	return false;
}

#ifdef WIN32
	HANDLE* mappedFiles = new HANDLE[5];
	HANDLE* mappings = new HANDLE[5];
#else
	FILE** disks = new FILE*[5];
#endif
	char** mappedDataArray = new char*[5];

int mapping(int nDisks, int nBlocks, int blockSize, bool rebuild) {
	char DiskNm[10];
	void* mappedData;

#ifdef WIN32
	HFILE mappedFile;
	HANDLE mapping;
	OFSTRUCT buff;
#else
	FILE * disk;
#endif

	for (int i = 1; i <= nDisks; i++) {
		sprintf(DiskNm, "Disk%i", i);
		
#ifdef WIN32
		mappedFile = OpenFile(DiskNm, &buff, OF_READWRITE);
		if ((mappedFile == HFILE_ERROR)&&(!rebuild)) {
			cout << "Can't open file " << DiskNm << "\n";
			return 1;
		}
		mappedFiles[i] = (HANDLE) mappedFile;

		mapping = CreateFileMapping((HANDLE) mappedFile, NULL, PAGE_READWRITE,
				0, 0, NULL);
		if ((mapping == NULL)&&(!rebuild)) {
			cout << "Mapping error.\n";
			return 1;
		}
		mappings[i] = mapping;

		mappedData = MapViewOfFile(mapping, FILE_MAP_WRITE, 0, 0, 0);
		if ((mappedData == NULL)&&(!rebuild)) {
			cout << "Mapping error.\n";
			return 1;
		}
		mappedDataArray[i] = (char*)mappedData;

#else
		disk = fopen(DiskNm, "wb+");
		disks[i] = disk;
		mappedData = mmap(0, nBlocks * blockSize, PROT_WRITE|PROT_READ, MAP_SHARED, fileno(disk), 0);
		if (mappedData == MAP_FAILED) {
			if (rebuild) {
				mappedDataArray[i] = NULL;
				return 0;
			} else {
				cout << "Mapping error. " << DiskNm << ".\n";
				return 1;
			}
		}
		mappedDataArray[i] = (char*)mappedData;
#endif
	}

	return 0;
}

int unmapping(int nDisks, int nBlocks, int blockSize, bool rebuild) {
	for (int i = 1; i <= nDisks; i++) {
#ifdef WIN32
		if ((UnmapViewOfFile(mappedDataArray[i]) == 0)&&(!rebuild)) {
			cout << "Unmapping error.\n";
			return 1;
		}
		if ((CloseHandle(mappings[i]) == 0)&&(!rebuild)) {
			cout << "Closing mapping error\n";
			return 1;
		}
		if ((CloseHandle(mappedFiles[i]) == 0)&&(!rebuild)) {
			cout << "Closing mapped file error\n";
			return 1;
		}
#else
		if ((munmap(mappedDataArray[i], nBlocks * blockSize) == -1)&&(!rebuild)) {
			cout << "Unmapping error.\n";
		}
		fclose(disks[i]);
#endif

	}
#ifdef WIN32
	delete[] mappedFiles;
	delete[] mappings;
#else
	delete[] disks;
#endif
	delete[] mappedDataArray;
	return 0;
}

#endif /* UTILS_H_ */
